package cn.bx.bid.ctrl;

import cn.bx.bid.entity.*;
import cn.bx.bid.service.ProjectService;
import cn.bx.bid.util.LogUtil;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
public class ProjectController {
    @Autowired
    ProjectService projectService;
    @RequestMapping(value="/projectSearch",produces = "application/json;charset=utf-8")
    public Page<Project> paging(@RequestParam(name="page",defaultValue = "1")int pageNo, @RequestParam(name = "limit", defaultValue = "10") int limit, @RequestParam(name = "name", required = false) String name, @RequestParam(name = "category", required = false) String category){
        Page<Project> p=this.projectService.paging(pageNo,limit,name,category);
        return p;
    }
    @RequestMapping(value="/projectChoosingProfs",produces = "application/json;charset=utf-8")
    public AjaxResult projectChoosingProfs(@RequestParam(name="projid")long projid){
        List<ProfessorEnroll> p = this.projectService.searchProfessorInProjs(projid);
        return AjaxResult.success(p);
    }
    @RequestMapping(value="/randomSelect",produces = "application/json;charset=utf-8")
    public AjaxResult randomSelect(@RequestParam(name="pjid")long pjid, @RequestParam(name="category")String category, @RequestParam(name="distance")Double distance){

        Project p = this.projectService.get(pjid);
        //考虑了能来的，去掉确定不来的，不确定的也加上了
        int hasSelected = this.projectService.getPrentProfessors(pjid);
        String msg = "";
        try {
            if (p.getStatus() == 1) {
                msg = "此项目已经结束，不能再选";
                return AjaxResult.error(msg);
            } else if (hasSelected >= p.getProfessorNum()) {
                msg = "此项目人数已经满足，无需再选";
                return AjaxResult.error(msg);
            } else {
                List<Professor> list = projectService.getProfessorsForChoose(pjid, category);
                //
                if (distance != null ) {//distance>0
                    //根据距离过滤
                    Jw location = getPos(p.getAddress());//项目开标地址的经纬度
                    System.out.println("开会地点。。。。。。" + location);
                    if (location != null) {
                        Iterator<Professor> r = list.iterator();
                        while (r.hasNext()) {
                            Professor t = r.next();
                            Jw l2 = getPos(t.getAddress());//获得专家的经纬度
                            if (l2 == null)
                                continue;//地址不确定的先不考虑
                            System.out.println("专家：" + t.getProfessorname() + " 住址：" + l2 + ">>>距离：" + l2.dis(location) + "公里");
                            if (l2.dis(location) > distance) {
                                r.remove();//删除当前专家
                            }
                        }
                    }
                }
                if (list.size() < (p.getProfessorNum() - hasSelected)) {
                    msg = "没有找到满足人数的专家，缺少"+(Math.abs(list.size() - (p.getProfessorNum() - hasSelected)))+"人，先修改条件或者重新选择距离再试";
                    return AjaxResult.error(msg);
                } else {
                    //开始随机选择
                    int need = p.getProfessorNum() - hasSelected;
                    long ids[] = new long[need];
                    int index = 0;
                    while (true) {
                        int r = (int) (Math.random() * list.size());
                        ids[index++] = list.get(r).getId();
                        list.remove(r);
                        if (index >= ids.length)
                            break;
                    }
                    //保存到数据库
                    int result = this.projectService.saveChooseResult(p, ids);
                    msg = "成功抽选"+need+"名专家";
                    return AjaxResult.success(msg);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            msg = "网络不稳定，稍后再试！";
            return AjaxResult.error(msg);
        }
    }
    @RequestMapping(value="/projectAdd",produces = "application/json;charset=utf-8")
    public String add(HttpSession s, @ModelAttribute("p") Project p, @RequestParam(name = "fujian",required = false) MultipartFile file){
        LogUtil.info("fffffffffff="+file);
        if(!(file==null||file.isEmpty())){
            //文件后缀 getName()
            String oldName=file.getOriginalFilename();
            String prefix=oldName.substring(oldName.lastIndexOf('.'));
            //新文件名
            String newName= UUID.randomUUID()+prefix;
            //保存到项目的doc目录下
            File path=new File(s.getServletContext().getRealPath("doc"));
            LogUtil.info("文件的路径："+path.getAbsolutePath());
            if(path.exists()==false)
                path.mkdirs();

            try {
                file.transferTo(new File(path,newName));
                p.setProjectFilePath(newName);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        LogUtil.info("新项目的信息时：\n"+p);
        projectService.add(p);
        return "addsuccess";
    }

    //确定参加
    @RequestMapping(value="/profRoleProject",produces = "application/json;charset=utf-8")
    public AjaxResult profRoleProject(@RequestParam(name = "pfid")Long pfid, @RequestParam(name = "projid")Long projid) {

        int r=this.projectService.profRoleProject(pfid,projid);
        if(r==1)
            return AjaxResult.success();
        return AjaxResult.error();

    }

    //不参加
    @RequestMapping(value="/profnotPresentProject",produces = "application/json;charset=utf-8")
    public AjaxResult profnotPresentProject(@RequestParam(name = "pfid")Long pfid, @RequestParam(name = "projid")Long projid,@RequestParam(name = "reason")String reason){
        //待续
        int r=this.projectService.profnotPresentProject(pfid,projid,reason);
        if(r==1)
            return AjaxResult.success();
        return AjaxResult.error();

    }
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
        // true:允许输入空值，false:不能为空值
    }
    public static final String url = "http://api.map.baidu.com/geocoder/v2/?address=%s&output=json&ak=B4bd9e22c0a580cd04b0e84b17bf9eb6";

    // 获得经纬度
    private Jw getPos(String addr) {
        try {
            addr= URLEncoder.encode(addr,"utf-8");
        } catch (Exception e) {
        }
        String str = getDistance(String.format(url, addr));
        Map m = (Map) JSON.parse(str);

        if (!new Integer(0).equals(m.get("status"))) {
            return null;
        }
        Map m2 = (Map) ((Map) m.get("result")).get("location");
        System.out.println(m2);
        double lng = Double.parseDouble(m2.get("lng").toString());
        double lat = Double.parseDouble(m2.get("lat").toString());
        return new Jw(lat, lng);
    }
    public String getDistance(String url) {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        // 创建Get请求
        HttpGet httpGet = new HttpGet(url);

        // 响应模型
        CloseableHttpResponse response = null;
        try {
            // 由客户端执行(发送)Get请求
            response = httpClient.execute(httpGet);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("响应内容长度为:" + responseEntity.getContentLength());
                // System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
                return EntityUtils.toString(responseEntity);
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

class Jw {
    public double lat, lng;

    public Jw() {
    }

    public Jw(double lat, double lng) {
        super();
        this.lat = lat;
        this.lng = lng;
    }

    public double dis(Jw w) {
        return getDistance(this.lat, this.lng, w.lat, w.lng);
    }

    @Override
    public String toString() {
        return "Jw [lat=" + lat + ", lng=" + lng + "]";
    }

    public static double getDistance(double Lat_A, double Lng_A, double Lat_B, double Lng_B) {
        double ra = 6378.140;
        double rb = 6356.755;
        double flatten = (ra - rb) / ra;
        double rad_lat_A = Math.toRadians(Lat_A);
        double rad_lng_A = Math.toRadians(Lng_A);
        double rad_lat_B = Math.toRadians(Lat_B);
        double rad_lng_B = Math.toRadians(Lng_B);
        double pA = Math.atan(rb / ra * Math.tan(rad_lat_A));
        double pB = Math.atan(rb / ra * Math.tan(rad_lat_B));
        double xx = Math
                .acos(Math.sin(pA) * Math.sin(pB) + Math.cos(pA) * Math.cos(pB) * Math.cos(rad_lng_A - rad_lng_B));
        double c1 = (Math.sin((xx) - xx) * (Math.sin(pA) + Math.sin(pB)) * 2 / Math.cos(xx / 2) * 2);
        double c2 = (Math.sin(xx) + xx) * (Math.sin(pA) - Math.sin(pB)) * 2 / Math.sin(xx / 2) * 2;
        double dr = flatten / 8 * (c1 - c2);
        double distance = ra * (xx + dr);
        // DecimalFormat format = new DecimalFormat("###.000");
        // distance = Double.parseDouble(format.format(distance));
        return Math.abs(distance);
    }
}